<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>原型对象</title>
</head>

<body>
  <script>
    // Object.create(target),返回一个继承了target对象属性的新对象
    /*  let target = {a:1}
     let obj = Object.create(target)
     console.log(obj);
     // 输出obj的原型对象，再一般对象上，通过 __proto__ 属性来获取原型对象。
     let prototypeObj = obj.__proto__; // __proto__, 注意，这里是2个下划线
     console.log(prototypeObj); //{a: 1}， 原型对象上面的属性和方法，对象都可以直接使用的。
     console.log(obj.a); // 1 */

    // 构造函数：
    /*  function Person(name) {
       this.name = name;
     }
     // 构造函数通过 prototype 属性，来获取构造函数的原型对象。
 
     console.log(Person.prototype);    // {constructor: ƒ} ,有一个 构造器的函数
     Person.prototype.read = function (t) {
       console.log(this.name + "在读" + t);
     }
     console.log(Person.prototype);  // {read: ƒ, constructor: ƒ}
     
     let p = new Person('张三') // 实例化对象是可以继承构造函数的原型对象上面的属性和方法的。
     console.log(p);// Person {name: '张三'}
     p.read('望天书') //张三在读望天书
 
     console.log(p.__proto__);// {read: ƒ, constructor: ƒ}
 
     // 实例化对象的原型对象和构造函数的原型对象是同一个对象。 他们获取对象的方式不同！！！
     // 实例化对象的原型对象： __proto__
     // 构造函数的原型对象: prototype
     // 原型对象的原型对象： __proto__
     console.log(p.__proto__ === Person.prototype);  // true
  */
    function Person(name) {
      this.name = name;
    }
    Person.prototype.read = function (t) {
      console.log(this.name + "在读" + t);
    }
    console.log(Person.prototype);  // {read: ƒ, constructor: ƒ}
    console.log(Person.prototype.__proto__); // Object()构造函数，是JavaScript中最顶层的原型对象。
    console.log(Person.prototype.__proto__.__proto__); // null,表示没有上一层的原型对象了。

    // 在最顶层的Object原型对象上面，扩展一个方法：
    Person.prototype.__proto__.mywrite=function(){
      console.log("writing....");
    }

    // 实例化对象p，是可以调用mywrite()的。
    let p = new Person('李4')
    p.read('销售宝典')
    p.mywrite(); // writing....

    // 当一个对象调用某一个属性、方法的时候，它先绑定自己有没有这个属性或方法；
    // 如果没有，就去访问它的原型对象，看原型对象上面有没有。如果第一层原型对象也没有，就再向上一层原型对象访问。
    // 依此类推，直到找到最顶层的Object原型对象。再这个过程中，都在不到，就报错：'没有这个属性或方法。'
    // 如果再某一层原型对象上面找到了， 就直接使用这个属性或方法。
    // 我们查找这个属性或方法时，所访问的路径，就叫原型链。

    // p.find() //报的错：p.find is not a function  表示没有这个方法
    // console.log(p.xxx); // undefined, 这里表示没有这个属性
  </script>
</body>

</html>